"""
Flask工具函数示例 - 展示各种实用工具函数的使用
包含数据验证、格式化、加密、文件处理、时间处理等功能
"""

from flask import Flask, request, jsonify, send_file
import os
import sys
import io
import json
from datetime import datetime, timedelta
from typing import Dict, Any, List, Optional
import tempfile

# 添加项目根目录到Python路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from python_backend_toolkit.utils import (
    generate_uuid, generate_random_string, generate_hash,
    validate_email, validate_phone, validate_url,
    format_datetime, parse_datetime, get_timestamp,
    sanitize_filename, ensure_directory,
    retry_on_failure, rate_limit,
    deep_merge, flatten_dict, unflatten_dict,
    chunk_list, deduplicate_list,
    safe_json_loads, safe_json_dumps,
    mask_sensitive_data, extract_domain_from_url,
    calculate_file_hash, compress_string, decompress_string
)
from python_backend_toolkit.logging import get_logger
from python_backend_toolkit.api.responses import SuccessResponse, ErrorResponse


# ========================================================================
# 工具函数扩展
# ========================================================================

class DataProcessor:
    """数据处理工具类"""
    
    def __init__(self):
        self.logger = get_logger("DataProcessor")
    
    def process_user_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """处理用户数据"""
        processed = {}
        
        # 验证和清理邮箱
        if 'email' in data:
            email = data['email'].strip().lower()
            if validate_email(email):
                processed['email'] = email
            else:
                raise ValueError(f"Invalid email: {email}")
        
        # 验证和格式化手机号
        if 'phone' in data:
            phone = data['phone'].strip()
            if validate_phone(phone):
                processed['phone'] = phone
            else:
                raise ValueError(f"Invalid phone: {phone}")
        
        # 处理用户名
        if 'username' in data:
            username = data['username'].strip()
            if len(username) < 3:
                raise ValueError("Username must be at least 3 characters")
            processed['username'] = username
        
        # 生成用户ID
        processed['id'] = generate_uuid()
        processed['created_at'] = format_datetime(datetime.utcnow())
        
        # 掩码敏感信息用于日志
        safe_data = mask_sensitive_data(processed, ['email', 'phone'])
        self.logger.info("User data processed", data=safe_data)
        
        return processed
    
    def generate_secure_token(self, length: int = 32) -> str:
        """生成安全令牌"""
        token = generate_random_string(length)
        token_hash = generate_hash(token)
        
        self.logger.info(
            "Secure token generated",
            token_length=length,
            token_hash=token_hash[:8] + "..."
        )
        
        return token
    
    def process_file_upload(self, file_data: bytes, filename: str) -> Dict[str, Any]:
        """处理文件上传"""
        # 清理文件名
        safe_filename = sanitize_filename(filename)
        
        # 计算文件哈希
        file_hash = calculate_file_hash(file_data)
        
        # 生成唯一文件名
        file_id = generate_uuid()
        extension = os.path.splitext(safe_filename)[1]
        unique_filename = f"{file_id}{extension}"
        
        # 文件信息
        file_info = {
            "id": file_id,
            "original_name": filename,
            "safe_name": safe_filename,
            "unique_name": unique_filename,
            "size": len(file_data),
            "hash": file_hash,
            "uploaded_at": format_datetime(datetime.utcnow())
        }
        
        self.logger.info(
            "File upload processed",
            file_id=file_id,
            original_name=filename,
            size=len(file_data),
            hash=file_hash
        )
        
        return file_info


class ConfigManager:
    """配置管理工具"""
    
    def __init__(self):
        self.logger = get_logger("ConfigManager")
        self.config = {}
    
    def load_config(self, config_data: Dict[str, Any]) -> Dict[str, Any]:
        """加载配置"""
        # 默认配置
        default_config = {
            "app": {
                "name": "Flask Utils Demo",
                "version": "1.0.0",
                "debug": False
            },
            "database": {
                "url": "sqlite:///app.db",
                "pool_size": 10
            },
            "cache": {
                "type": "memory",
                "ttl": 3600
            },
            "security": {
                "secret_key": generate_random_string(32),
                "token_expiry": 86400
            }
        }
        
        # 合并配置
        self.config = deep_merge(default_config, config_data)
        
        # 展平配置用于环境变量覆盖
        flat_config = flatten_dict(self.config)
        
        self.logger.info(
            "Configuration loaded",
            config_keys=list(self.config.keys()),
            flat_keys_count=len(flat_config)
        )
        
        return self.config
    
    def get_config(self, key: str, default=None):
        """获取配置值"""
        keys = key.split('.')
        value = self.config
        
        for k in keys:
            if isinstance(value, dict) and k in value:
                value = value[k]
            else:
                return default
        
        return value
    
    def update_config(self, updates: Dict[str, Any]):
        """更新配置"""
        self.config = deep_merge(self.config, updates)
        self.logger.info("Configuration updated", updates=updates)


class DataValidator:
    """数据验证工具"""
    
    def __init__(self):
        self.logger = get_logger("DataValidator")
    
    def validate_user_registration(self, data: Dict[str, Any]) -> Dict[str, List[str]]:
        """验证用户注册数据"""
        errors = {}
        
        # 验证用户名
        username = data.get('username', '').strip()
        if not username:
            errors.setdefault('username', []).append("Username is required")
        elif len(username) < 3:
            errors.setdefault('username', []).append("Username must be at least 3 characters")
        elif len(username) > 50:
            errors.setdefault('username', []).append("Username must be less than 50 characters")
        
        # 验证邮箱
        email = data.get('email', '').strip()
        if not email:
            errors.setdefault('email', []).append("Email is required")
        elif not validate_email(email):
            errors.setdefault('email', []).append("Invalid email format")
        
        # 验证密码
        password = data.get('password', '')
        if not password:
            errors.setdefault('password', []).append("Password is required")
        elif len(password) < 8:
            errors.setdefault('password', []).append("Password must be at least 8 characters")
        
        # 验证手机号（可选）
        phone = data.get('phone', '').strip()
        if phone and not validate_phone(phone):
            errors.setdefault('phone', []).append("Invalid phone format")
        
        # 验证网站URL（可选）
        website = data.get('website', '').strip()
        if website and not validate_url(website):
            errors.setdefault('website', []).append("Invalid URL format")
        
        self.logger.info(
            "User registration validation completed",
            has_errors=bool(errors),
            error_fields=list(errors.keys()) if errors else []
        )
        
        return errors
    
    def validate_api_request(self, data: Dict[str, Any], schema: Dict[str, Any]) -> Dict[str, List[str]]:
        """验证API请求数据"""
        errors = {}
        
        # 检查必需字段
        required_fields = schema.get('required', [])
        for field in required_fields:
            if field not in data or not data[field]:
                errors.setdefault(field, []).append(f"{field} is required")
        
        # 检查字段类型
        field_types = schema.get('types', {})
        for field, expected_type in field_types.items():
            if field in data:
                value = data[field]
                if expected_type == 'string' and not isinstance(value, str):
                    errors.setdefault(field, []).append(f"{field} must be a string")
                elif expected_type == 'integer' and not isinstance(value, int):
                    errors.setdefault(field, []).append(f"{field} must be an integer")
                elif expected_type == 'list' and not isinstance(value, list):
                    errors.setdefault(field, []).append(f"{field} must be a list")
        
        # 检查字段长度
        field_lengths = schema.get('lengths', {})
        for field, length_config in field_lengths.items():
            if field in data and isinstance(data[field], str):
                value = data[field]
                min_length = length_config.get('min', 0)
                max_length = length_config.get('max', float('inf'))
                
                if len(value) < min_length:
                    errors.setdefault(field, []).append(
                        f"{field} must be at least {min_length} characters"
                    )
                if len(value) > max_length:
                    errors.setdefault(field, []).append(
                        f"{field} must be less than {max_length} characters"
                    )
        
        return errors


def create_utils_app() -> Flask:
    """创建工具函数示例Flask应用"""
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'utils-demo-secret'
    
    logger = get_logger("UtilsApp")
    
    # 初始化工具类
    data_processor = DataProcessor()
    config_manager = ConfigManager()
    data_validator = DataValidator()
    
    # 加载默认配置
    config_manager.load_config({})
    
    # ========================================================================
    # 数据处理API
    # ========================================================================
    
    @app.route('/utils/process-user', methods=['POST'])
    def process_user():
        """处理用户数据"""
        try:
            data = request.get_json()
            
            if not data:
                return jsonify(ErrorResponse.create(
                    message="Request data is required"
                ).dict()), 400
            
            processed_data = data_processor.process_user_data(data)
            
            response = SuccessResponse.create(
                data={"processed_user": processed_data},
                message="User data processed successfully"
            )
            return jsonify(response.dict())
            
        except ValueError as e:
            return jsonify(ErrorResponse.create(
                message=str(e)
            ).dict()), 400
        except Exception as e:
            logger.error("Error processing user data", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to process user data"
            ).dict()), 500
    
    @app.route('/utils/generate-token', methods=['POST'])
    def generate_token():
        """生成安全令牌"""
        try:
            data = request.get_json() or {}
            length = data.get('length', 32)
            
            if not isinstance(length, int) or length < 8 or length > 128:
                return jsonify(ErrorResponse.create(
                    message="Length must be an integer between 8 and 128"
                ).dict()), 400
            
            token = data_processor.generate_secure_token(length)
            
            response = SuccessResponse.create(
                data={
                    "token": token,
                    "length": len(token),
                    "hash": generate_hash(token)
                },
                message="Token generated successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error generating token", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to generate token"
            ).dict()), 500
    
    @app.route('/utils/validate-data', methods=['POST'])
    def validate_data():
        """验证数据"""
        try:
            data = request.get_json()
            
            if not data:
                return jsonify(ErrorResponse.create(
                    message="Request data is required"
                ).dict()), 400
            
            validation_type = data.get('type', 'user_registration')
            payload = data.get('data', {})
            
            if validation_type == 'user_registration':
                errors = data_validator.validate_user_registration(payload)
            elif validation_type == 'api_request':
                schema = data.get('schema', {})
                errors = data_validator.validate_api_request(payload, schema)
            else:
                return jsonify(ErrorResponse.create(
                    message="Invalid validation type"
                ).dict()), 400
            
            response = SuccessResponse.create(
                data={
                    "valid": not bool(errors),
                    "errors": errors,
                    "validation_type": validation_type
                },
                message="Data validation completed"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error validating data", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to validate data"
            ).dict()), 500
    
    # ========================================================================
    # 文件处理API
    # ========================================================================
    
    @app.route('/utils/upload-file', methods=['POST'])
    def upload_file():
        """文件上传处理"""
        try:
            if 'file' not in request.files:
                return jsonify(ErrorResponse.create(
                    message="No file provided"
                ).dict()), 400
            
            file = request.files['file']
            if file.filename == '':
                return jsonify(ErrorResponse.create(
                    message="No file selected"
                ).dict()), 400
            
            # 读取文件数据
            file_data = file.read()
            
            # 处理文件
            file_info = data_processor.process_file_upload(file_data, file.filename)
            
            # 保存文件到临时目录（示例）
            temp_dir = tempfile.gettempdir()
            file_path = os.path.join(temp_dir, file_info['unique_name'])
            
            with open(file_path, 'wb') as f:
                f.write(file_data)
            
            file_info['temp_path'] = file_path
            
            response = SuccessResponse.create(
                data={"file_info": file_info},
                message="File uploaded and processed successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error uploading file", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to upload file"
            ).dict()), 500
    
    @app.route('/utils/sanitize-filename', methods=['POST'])
    def sanitize_filename_endpoint():
        """清理文件名"""
        try:
            data = request.get_json()
            filename = data.get('filename', '')
            
            if not filename:
                return jsonify(ErrorResponse.create(
                    message="Filename is required"
                ).dict()), 400
            
            safe_filename = sanitize_filename(filename)
            
            response = SuccessResponse.create(
                data={
                    "original": filename,
                    "sanitized": safe_filename,
                    "changed": filename != safe_filename
                },
                message="Filename sanitized successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error sanitizing filename", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to sanitize filename"
            ).dict()), 500
    
    # ========================================================================
    # 数据格式化API
    # ========================================================================
    
    @app.route('/utils/format-datetime', methods=['POST'])
    def format_datetime_endpoint():
        """格式化日期时间"""
        try:
            data = request.get_json()
            datetime_str = data.get('datetime')
            format_str = data.get('format', '%Y-%m-%d %H:%M:%S')
            
            if datetime_str:
                # 解析输入的日期时间
                dt = parse_datetime(datetime_str)
                if not dt:
                    return jsonify(ErrorResponse.create(
                        message="Invalid datetime format"
                    ).dict()), 400
            else:
                # 使用当前时间
                dt = datetime.utcnow()
            
            formatted = format_datetime(dt, format_str)
            timestamp = get_timestamp(dt)
            
            response = SuccessResponse.create(
                data={
                    "original": datetime_str,
                    "datetime": dt.isoformat(),
                    "formatted": formatted,
                    "timestamp": timestamp,
                    "format": format_str
                },
                message="Datetime formatted successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error formatting datetime", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to format datetime"
            ).dict()), 500
    
    @app.route('/utils/process-list', methods=['POST'])
    def process_list():
        """处理列表数据"""
        try:
            data = request.get_json()
            items = data.get('items', [])
            operation = data.get('operation', 'deduplicate')
            
            if not isinstance(items, list):
                return jsonify(ErrorResponse.create(
                    message="Items must be a list"
                ).dict()), 400
            
            result = {}
            
            if operation == 'deduplicate':
                result['processed'] = deduplicate_list(items)
                result['operation'] = 'deduplicate'
            elif operation == 'chunk':
                chunk_size = data.get('chunk_size', 10)
                result['processed'] = chunk_list(items, chunk_size)
                result['operation'] = 'chunk'
                result['chunk_size'] = chunk_size
            else:
                return jsonify(ErrorResponse.create(
                    message="Invalid operation"
                ).dict()), 400
            
            result['original_count'] = len(items)
            
            response = SuccessResponse.create(
                data=result,
                message="List processed successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error processing list", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to process list"
            ).dict()), 500
    
    # ========================================================================
    # 字典操作API
    # ========================================================================
    
    @app.route('/utils/merge-dicts', methods=['POST'])
    def merge_dicts():
        """合并字典"""
        try:
            data = request.get_json()
            dict1 = data.get('dict1', {})
            dict2 = data.get('dict2', {})
            
            if not isinstance(dict1, dict) or not isinstance(dict2, dict):
                return jsonify(ErrorResponse.create(
                    message="Both dict1 and dict2 must be dictionaries"
                ).dict()), 400
            
            merged = deep_merge(dict1, dict2)
            
            response = SuccessResponse.create(
                data={
                    "dict1": dict1,
                    "dict2": dict2,
                    "merged": merged
                },
                message="Dictionaries merged successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error merging dictionaries", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to merge dictionaries"
            ).dict()), 500
    
    @app.route('/utils/flatten-dict', methods=['POST'])
    def flatten_dict_endpoint():
        """展平字典"""
        try:
            data = request.get_json()
            input_dict = data.get('dict', {})
            separator = data.get('separator', '.')
            
            if not isinstance(input_dict, dict):
                return jsonify(ErrorResponse.create(
                    message="Input must be a dictionary"
                ).dict()), 400
            
            flattened = flatten_dict(input_dict, separator)
            
            response = SuccessResponse.create(
                data={
                    "original": input_dict,
                    "flattened": flattened,
                    "separator": separator
                },
                message="Dictionary flattened successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error flattening dictionary", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to flatten dictionary"
            ).dict()), 500
    
    @app.route('/utils/unflatten-dict', methods=['POST'])
    def unflatten_dict_endpoint():
        """反展平字典"""
        try:
            data = request.get_json()
            input_dict = data.get('dict', {})
            separator = data.get('separator', '.')
            
            if not isinstance(input_dict, dict):
                return jsonify(ErrorResponse.create(
                    message="Input must be a dictionary"
                ).dict()), 400
            
            unflattened = unflatten_dict(input_dict, separator)
            
            response = SuccessResponse.create(
                data={
                    "original": input_dict,
                    "unflattened": unflattened,
                    "separator": separator
                },
                message="Dictionary unflattened successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error unflattening dictionary", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to unflatten dictionary"
            ).dict()), 500
    
    # ========================================================================
    # 字符串处理API
    # ========================================================================
    
    @app.route('/utils/compress-string', methods=['POST'])
    def compress_string_endpoint():
        """压缩字符串"""
        try:
            data = request.get_json()
            text = data.get('text', '')
            
            if not text:
                return jsonify(ErrorResponse.create(
                    message="Text is required"
                ).dict()), 400
            
            compressed = compress_string(text)
            decompressed = decompress_string(compressed)
            
            response = SuccessResponse.create(
                data={
                    "original": text,
                    "original_size": len(text),
                    "compressed": compressed.hex(),  # 转换为十六进制字符串显示
                    "compressed_size": len(compressed),
                    "decompressed": decompressed,
                    "compression_ratio": len(compressed) / len(text) if text else 0
                },
                message="String compressed successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error compressing string", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to compress string"
            ).dict()), 500
    
    @app.route('/utils/mask-data', methods=['POST'])
    def mask_data():
        """掩码敏感数据"""
        try:
            data = request.get_json()
            input_data = data.get('data', {})
            sensitive_fields = data.get('sensitive_fields', [])
            
            if not isinstance(input_data, dict):
                return jsonify(ErrorResponse.create(
                    message="Data must be a dictionary"
                ).dict()), 400
            
            masked_data = mask_sensitive_data(input_data, sensitive_fields)
            
            response = SuccessResponse.create(
                data={
                    "original": input_data,
                    "masked": masked_data,
                    "sensitive_fields": sensitive_fields
                },
                message="Data masked successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error masking data", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to mask data"
            ).dict()), 500
    
    # ========================================================================
    # 配置管理API
    # ========================================================================
    
    @app.route('/utils/config', methods=['GET'])
    def get_config():
        """获取配置"""
        try:
            key = request.args.get('key')
            
            if key:
                value = config_manager.get_config(key)
                if value is None:
                    return jsonify(ErrorResponse.create(
                        message=f"Configuration key '{key}' not found"
                    ).dict()), 404
                
                result = {"key": key, "value": value}
            else:
                result = {"config": config_manager.config}
            
            response = SuccessResponse.create(
                data=result,
                message="Configuration retrieved successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error getting configuration", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to get configuration"
            ).dict()), 500
    
    @app.route('/utils/config', methods=['POST'])
    def update_config():
        """更新配置"""
        try:
            data = request.get_json()
            
            if not data:
                return jsonify(ErrorResponse.create(
                    message="Configuration data is required"
                ).dict()), 400
            
            config_manager.update_config(data)
            
            response = SuccessResponse.create(
                data={"updated_config": config_manager.config},
                message="Configuration updated successfully"
            )
            return jsonify(response.dict())
            
        except Exception as e:
            logger.error("Error updating configuration", error=str(e))
            return jsonify(ErrorResponse.create(
                message="Failed to update configuration"
            ).dict()), 500
    
    # ========================================================================
    # 应用信息
    # ========================================================================
    
    @app.route('/health', methods=['GET'])
    def health_check():
        """健康检查"""
        return jsonify({
            "status": "healthy",
            "timestamp": datetime.utcnow().isoformat(),
            "utils": "active"
        })
    
    @app.route('/info', methods=['GET'])
    def app_info():
        """应用信息"""
        return jsonify({
            "name": "Flask Utils Example",
            "version": "1.0.0",
            "description": "Flask工具函数示例应用",
            "utility_categories": [
                "数据处理",
                "数据验证",
                "文件处理",
                "日期时间格式化",
                "字符串处理",
                "字典操作",
                "配置管理"
            ],
            "endpoints": {
                "data_processing": [
                    "POST /utils/process-user",
                    "POST /utils/generate-token",
                    "POST /utils/validate-data"
                ],
                "file_processing": [
                    "POST /utils/upload-file",
                    "POST /utils/sanitize-filename"
                ],
                "formatting": [
                    "POST /utils/format-datetime",
                    "POST /utils/process-list"
                ],
                "dict_operations": [
                    "POST /utils/merge-dicts",
                    "POST /utils/flatten-dict",
                    "POST /utils/unflatten-dict"
                ],
                "string_processing": [
                    "POST /utils/compress-string",
                    "POST /utils/mask-data"
                ],
                "configuration": [
                    "GET  /utils/config",
                    "POST /utils/config"
                ]
            },
            "features": [
                "数据验证和清理",
                "安全令牌生成",
                "文件上传处理",
                "日期时间格式化",
                "字符串压缩",
                "敏感数据掩码",
                "字典深度合并",
                "配置管理"
            ]
        })
    
    return app


if __name__ == '__main__':
    app = create_utils_app()
    
    print("=" * 60)
    print("Flask Utils Example")
    print("=" * 60)
    print("工具函数功能演示:")
    print("  数据处理:")
    print("    POST /utils/process-user - 处理用户数据")
    print("    POST /utils/generate-token - 生成安全令牌")
    print("    POST /utils/validate-data - 验证数据")
    print()
    print("  文件处理:")
    print("    POST /utils/upload-file - 文件上传处理")
    print("    POST /utils/sanitize-filename - 清理文件名")
    print()
    print("  格式化:")
    print("    POST /utils/format-datetime - 格式化日期时间")
    print("    POST /utils/process-list - 处理列表数据")
    print()
    print("  字典操作:")
    print("    POST /utils/merge-dicts - 合并字典")
    print("    POST /utils/flatten-dict - 展平字典")
    print("    POST /utils/unflatten-dict - 反展平字典")
    print()
    print("  字符串处理:")
    print("    POST /utils/compress-string - 压缩字符串")
    print("    POST /utils/mask-data - 掩码敏感数据")
    print()
    print("  配置管理:")
    print("    GET  /utils/config - 获取配置")
    print("    POST /utils/config - 更新配置")
    print()
    print("  特性:")
    print("    - 数据验证和清理")
    print("    - 文件处理和安全")
    print("    - 日期时间工具")
    print("    - 字符串压缩和掩码")
    print("    - 字典深度操作")
    print("    - 配置管理")
    print("=" * 60)
    
    app.run(
        host='0.0.0.0',
        port=5006,
        debug=True
    )